﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Design;
using System.Linq;
using System.ComponentModel;

namespace Core
{
    public enum TypeOfNode
    {
        [Description("Клиентский порт")]
        Client,
        [Description("Серверный порт")]
        Server,
        [Description("Метод процесса")]
        Method
        
    }

    public class Node:FilterablePropertyBase,IGraphElement
    {

        [DisplayName("Id")]
        [Description("Поле Id")]
        [Category("1. Данные")]
        public String Id { get; set; }

        [DisplayName("Module")]
        [Description("Поле Module")]
        [Category("1. Данные")]
        public String Module { get; set; }

        [Category("2. Положение")]
        public int X { get; set; }
        [Category("2. Положение")]
        public int Y { get; set; }

        [Browsable(false)]
        public int Xold { get; private set; }
        [Browsable(false)]
        public int Yold { get; private set; }
        [Browsable(false)]
        public List<Link> Linking;

        [DisplayName("Тип узла")]
        [Category("1. Данные")]
        [TypeConverter(typeof(EnumTypeConverter))]
        public TypeOfNode Nodetype { get; set; }

        private bool _isStart = false;
        [DisplayName("await")]
        [Description("")]
        [DynamicPropertyFilter("Nodetype", "Method")]
        [Category("1. Данные")]
        public int _exit { get; set; }

        [Browsable(false)]
        public int Number { get; set; }

        [Browsable(false)]
        public bool IsSelected { get; set; }

        [Category("1. Данные")]
        public string Chanel
        {
            get { return _chanelName; }
            set{}
        }

        private Graph.TypeOfGraph _typeOfGraph;

        private string _chanelName="";

        public Node(int x, int y, String name, TypeOfNode nodetype,Graph.TypeOfGraph typeOfGraph)
        {
            _typeOfGraph = typeOfGraph;
            Linking = new List<Link>();
            Id = name;
            X = x;
            Y = y;
            Nodetype = nodetype;
            IsSelected = false;
        }
        
        public void SetChanel(string s)
        {
            _chanelName = s;
        }

        public void SavePos()
        {
            Xold = X;
            Yold = Y;
        }

        public void SetLink(Node node,string label)
        {
            Linking.Add(new Link(node,this,0,label,_typeOfGraph));
        }

        public void DeleteLink(Link selected)
        {
            Linking.Remove(selected);
        }

        public void SetExit(int ex)
        {
            _exit = ex;
        }

        public int GetPryoryty()
        {
            for (int i = 0; i < Linking.Count+1; i++)
            {
                if (Linking.Where(x => x.Value == i+1).ToArray().Length == 0)
                    return i + 1;
            }
            return 0;
        }

        public void Select()
        {
            IsSelected = true;
        }

        public void UnSelect()
        {
            IsSelected = false;
        }

        public void SetNodeType(byte nodetype)
        {
            Nodetype = (TypeOfNode) nodetype;
        }

        public byte GetNodeType()
        {
            return (byte) Nodetype;
        }

        public void MakeStart(Graph graph)
        {
            _isStart = true;
            graph.SetStartNode(this);
        }

        public void DrawNode(Graphics graphics)
        {
            Pen co = new Pen(Color.Black,2);
            if (IsSelected)
                co = new Pen(Color.Red,3);
            if(Nodetype == TypeOfNode.Method)
                graphics.DrawString(Id, new Font("Arial", 12), new SolidBrush(Color.Black), X-10 , Y-35 );
            else
            {
                if (!string.IsNullOrEmpty(Module))
                {
                    graphics.DrawString(Id + ':' + Module + '.' + _chanelName, new Font("Arial", 12), new SolidBrush(Color.Black), X - 10, Y - 35);
                }
                else
                {
                    graphics.DrawString(Id + ':' + _chanelName, new Font("Arial", 12), new SolidBrush(Color.Black), X - 10, Y - 35);
                }
                
            }
            SolidBrush redBrush = new SolidBrush(Color.Yellow);
            if (_isStart)
            {
               redBrush = new SolidBrush(Color.DimGray); 
            }
            
            switch (Nodetype)
            {

                case TypeOfNode.Client:
                    {
                        graphics.DrawEllipse(co, X - 15, Y - 15, 30, 30);
                        graphics.FillEllipse(redBrush, X - 15, Y - 15, 30, 30);
                        graphics.DrawString("C", new Font("Arial", 12), new SolidBrush(Color.Black),X-10,Y-10);
                        break;
                    }
                case TypeOfNode.Server:
                    {
                        graphics.DrawEllipse(co, X - 15, Y - 15, 30, 30);
                        graphics.FillEllipse(redBrush, X - 15, Y - 15, 30, 30);
                        graphics.DrawString("S", new Font("Arial", 12), new SolidBrush(Color.Black), X - 10, Y - 10);
                        break;
                    }
                case TypeOfNode.Method:
                    {
                        graphics.DrawEllipse(co, X - 15, Y - 15, 30, 30);
                        graphics.FillEllipse(redBrush, X - 15, Y - 15, 30, 30);
                        graphics.DrawString(_exit.ToString(), new Font("Arial", 12), new SolidBrush(Color.Black), X - 10, Y - 10);
                        break;
                    }
            }
        }

        public override string ToString()
        {
            string result= "";
            string type = "";
            string name = "";
            
            switch (Nodetype)
            {
                case TypeOfNode.Method:
                    {
                        name = "method";
                        break;
                    }
                case TypeOfNode.Server:
                    {
                        name = "port";
                        type = "srv";
                        break;
                    }
                 case TypeOfNode.Client:
                    {
                        name = "port";
                        type = "cli";
                        break;
                    }
                default:
                    {
                        type = "port"; 
                        break;
                    }
            }
            if (_typeOfGraph == Graph.TypeOfGraph.Chenal)
            {
                name = "state";
            }
            result += "\t"+"<"+name+" id="+'"'+Id+'"';
            if(Nodetype == TypeOfNode.Method)
            {
                result += " await=" + '"' + _exit.ToString() + '"';

            }else
            {
                if (_typeOfGraph == Graph.TypeOfGraph.Process)
                {
                    result += " channel=" + '"' + _chanelName + '"' + " module=" + '"' + Module + '"';
                    
                }
                result+= " type=" + '"' + type + '"';
            }
            result += " x=" + '"' + X + '"' + " y=" + '"' + Y + '"' + " rem=" + '"' + '"'+'>'+"\r\n";
            foreach (Link link in Linking)
            {
                result +="\t\t"+ link.ToString();
            }
            result += "\t</" + name + '>' + "\r\n";
            //result += "<node label="+'"'+ Id+ '"'+ " stub="+'"'+IsStub.ToString()+'"';
            //result += " id="+ '"'+ Id +'"'+ " module="+'"'+ Module + '"';
            //result += " exit=";
            //result += '"';
            //result += _exit.ToString();
            //result += '"';
            //result += " x=";result += '"';
            //result += X.ToString();result += '"';result += " y=";
            //result += '"';result += Y.ToString();result += '"';result += ">";
            return result;
        }
    }
}
